home *** CD-ROM | disk | FTP | other *** search
- /* savefile.c - storying regular files into (tape) archive
- * This is the part of the Tar program (see file tar.c)
- * Author: T.V.Shaporev
- * Creation date 11 Mar 1993
- */
- #include <stdio.h>
-
- #include "sysup.h"
- #include "modern.h"
- #include "compress.h"
- #include "define.h"
-
- extern char longname[];
-
- extern void proctl __ARGS__(( char *, long ));
- extern void prcsum __ARGS__(( register struct header * ));
- extern void newhead __ARGS__(( char *, long ));
- extern char *deleft __ARGS__(( char * ));
-
- #ifdef UNIX
- static werelost = FALSE;
- #endif
-
- #ifdef MSDOS
- # include <string.h>
- # ifdef __TURBOC__
- # include <dir.h>
- # else
- # include <direct.h>
- # endif
- # include <io.h>
-
- static int skipdots __ARGS__(( char *, int ));
- static int unperiod __ARGS__(( char *, int ));
- static int nextchar __ARGS__(( char *, int ));
-
- static int skipdots(char *s, int n)
- {
- while (n>0 && s[n]=='/' && s[n-1]=='.' && (n<2 || s[n-2]=='/'))
- n -= 2;
- return n;
- }
-
- static int unperiod(char *s, int n)
- {
- while (n>2 && s[n]=='/' && s[n-1]=='.' && s[n-2]=='.' && s[n-3]=='/') {
- if ((n -= 3) > 0) {
- for (n=nextchar(s, n); n>=0 && s[n]!='/'; n--) ;
- }
- }
- return n;
- }
-
- static int nextchar(char *s, int n)
- {
- if (n >= 0) n -= 1;
-
- while (n>0 && s[n]=='/' && s[n-1]=='.' &&
- ((n<2 || s[n-2]=='/') ||
- n>2 && s[n-2]=='.' && s[n-3]=='/')) {
- if (n>1 && s[n-2]=='.') {
- n = unperiod(s, n);
- } else {
- n = skipdots(s, n);
- }
- }
- return n;
- }
- #else
- int strlen();
- char *strcpy(), *strcat(), *strncpy();
- int open(), read(), close(), unlink();
- long lseek();
- #endif
- #include "lzpack.h"
- #include "roll.h"
-
- void cantopen(name)
- char *name;
- {
- (void)fprintf(myout, "Tar: can\'t open \'%s\'\n", name);
- }
-
- static void tmpput __ARGS__(( int ));
- static void no_mem __ARGS__(( int ));
- static void errproc __ARGS__(( char * ));
-
- static long this;
- static infile, ind;
-
- static int srcget __ARGS__(( void ))
- {
- if (++this > st.st_size) {
- return EOF;
- #if 0
- if (this == st.st_size + 1) return EOF;
- printf("@");
- /*errproc(hblock->name);*/
- #endif
- }
- if (ind >= pksize) {
- if (v_flag) percent(this, st.st_size);
- if (read(infile, pk_inp, pksize) < 1) errproc(hblock->name);
- ind = 0;
- }
- longcsum += ((unsigned char *)pk_inp)[ind];
- return ((unsigned char *)pk_inp)[ind++];
- }
-
- static void tmpput(c)
- int c;
- {
- ++codesize; if (rputc(c) != 0) errproc(hblock->name);
- }
-
- static void no_mem(flag)
- int flag;
- {
- (void)fprintf(stderr, "No memory for encoding.");
- if (flag) {
- (void)fprintf(stderr, " Continue? ");
- if (YES_NO()) return;
- } else {
- (void)fprintf(stderr, "\n");
- }
- done(ESMALL);
- }
-
- static void errproc(fname)
- char *fname;
- {
- (void)fprintf(myout, "\nTar: error processing \'%s\'\n", fname);
- done(EINTER);
- }
-
- void savefile(fname)
- char *fname;
- {
- register i; register c;
- register char *p;
- register long blocks;
- register packok;
- register struct node *t; struct node *prev;
-
- p = deleft(fname);
- if (u_flag) {
- if ((t = finditem(p, &prev, timehead)) != NONE) {
- i = t->info.time >= st.st_mtime;
- delitem(t, &timehead);
- if (i) return;
- }
- }
- if (isfile) {/* compare file to store with the archive one */
- #ifdef UNIX
- if (st.st_ino == sa.st_ino && st.st_dev == sa.st_dev) return;
- #endif
- #ifdef MSDOS
- /* The following comparison algorithm may fail */
- /* on combination of substed and real drives */
- register char *p1, *p2;
- register j1, j2;
- register d2;
- char b[2*MAXPATH];
-
- if (st.st_dev != sa.st_dev) goto next;
-
- /* Sinse 'st_dev' field gives the real drive number */
- /* there is no need to compare drive names */
-
- j1 = strlen(p1 = archname);
- p2 = fname;
- if (p2[0]>='a' && p2[0]<='z' && p2[1]==':') {
- d2 = p2[0] - ('a'-1);
- p2 += 2;
- } else {
- d2 = 0;
- }
- j2 = strlen(p2);
-
- while (j1>0 && p1[j1-1]!='/' && j2>0 && p2[j2-1]!='/') {
- if (p1[--j1] != p2[--j2]) goto next;
- }
- if (p2[0] != '/') {
- *(int *)b = '/';
- (void)getcurdir(d2, b+1);
- takename(b, b);
- i = strlen(b);
- b[i++] = '/';
- strcpy(b+i, p2);
- p2 = b;
- j2 += i;
- }
- do {
- j1 = nextchar(p1, j1);
- j2 = nextchar(p2, j2);
- if (j1 >= 0 && j2 >= 0 && p1[j1] != p2[j2]) goto next;
- } while (j1>=0 && j2>=0);
- if (j1 == j2) return;
- #endif
- }
- #ifdef MSDOS
- next: i = st.st_mode & 0700; st.st_mode |= (i>>3)|(i>>6);
- #endif
- if (w_flag && !okwork('a', ' ', &st, fname)) return;
-
- if ((infile = open(fname, O_RDONLY+O_BINARY)) < 0) {
- cantopen(fname); return;
- }
- newhead(fname, st.st_size);
- #ifdef UNIX
- if (st.st_nlink > 1) {
- prev = t = linkhead; i = 1;
- while (t && i>0) {
- i = st.st_ino - t->info.data.inode;
- if (!i) i = st.st_dev - t->info.data.device;
- if (i>0) { prev = t; t = t->next; }
- }
- if (i || !t) {/* entry not found */
- if ((t = additem(p, prev, &linkhead)) == NONE) {
- if (!werelost) {
- (void)fprintf(myout,
- "Tar: out of memory; link(s) lost\n");
- werelost = TRUE;
- }
- } else {
- t->info.data.count = st.st_nlink - 1;
- t->info.data.device = st.st_dev;
- t->info.data.inode = st.st_ino;
- }
- } else {/* previous entry found */
- (void)strncpy(hblock->linkname, t->name, MAXTNAME);
- hblock->filetype = TF_LNK;
- prcsum(hblock);
- if (v_flag) {
- (void)fprintf(myout, "a %s link to %s\n", p, t->name);
- }
- if (--(t->info.data.count) < 1) delitem(t, &linkhead);
- (void)close(infile);
- return;
- }
- }
- #endif
- blocks = (st.st_size + (BLKSIZE-1)) / BLKSIZE;
- packok = FALSE;
- if (blocks > 1) {
- if (pktype == PKLZH) {
- if (lzgetmem()!=0 || newroll("TAROLLXXXXXX")!=0) {
- lzrelmem(); delroll();
- #ifndef MSDOS
- if (!w_flag) {
- no_mem(0);
- } else
- #endif
- {
- no_mem(1);
- pktype = PKNONE;
- goto run;
- }
- }
- (void)rewroll(0);
- longcsum = 0; codesize = 0; this = 0;
- ind = pksize;
- if (v_flag) (void)fprintf(stderr, "e %s", p);
- (void)fflush(stderr);
- if (lzencode(srcget, tmpput) != st.st_size) {
- (void)fprintf(stderr, ": encoding error\n");
- done(EINTER);
- }
- }
- #ifdef USE_COMPRESS
- else if (pktype == PKfLZW) {
- if (strlen(hblock->name) > MAXTNAME-2) {
- #ifndef MSDOS
- if (!w_flag) {
- (void)fprintf(stderr, longname, hblock->name, "\n");
- } else
- #endif
- {
- (void)fprintf(stderr, longname, hblock->name,
- " Store uncompressed? ");
- if (YES_NO()) goto run;
- }
- return;
- }
- if (newroll("TAROLLXXXXXX")!=0) {
- delroll();
- #ifndef MSDOS
- if (!w_flag) {
- no_mem(0);
- } else
- #endif
- {
- no_mem(1);
- pktype = PKNONE;
- goto run;
- }
- }
- if ((i = z_gettab(pklevel)) < pklevel) {
- if (pklevel > 0) {
- #ifndef MSDOS
- if (!w_flag) {
- (void)fprintf(stderr, "Can only handle %d bits.\n", i);
- } else
- #endif
- {
- (void)fprintf(stderr,
- "Can only handle %d bits. Continue? ", i);
- pklevel = YES_NO() ? i : -1;
- }
- }
- if (pklevel <= 0) {
- no_mem(1);
- z_reltab();
- pktype = PKNONE;
- goto run;
- }
- }
- (void)rewroll(0);
- longcsum = 0; codesize = 0; this = 0;
- ind = pksize;
- if (v_flag) (void)fprintf(stderr, "z %s", p);
- (void)fflush(stderr);
-
- if (cbegin(pklevel, tmpput, st.st_size) < pklevel) no_mem(0);
- this = 0;
- do {
- if ((i = read(infile, pk_inp, pksize)) < 0) {
- errproc(hblock->name);
- }
- if (i > 0) {
- cpiece(pk_inp, i);
- if (v_flag) percent((this += i), st.st_size);
- }
- } while (i == pksize);
- codesize = cflush();
- }
- #endif
- if (v_flag) (void)fprintf(stderr, "\r");
- if (pkfile) {
- register long b;
-
- if ((b = (codesize + (BLKSIZE-1)) / BLKSIZE) < blocks) {
- packok = TRUE;
- blocks = b;
- } else if (lseek(infile, 0L, 0) < 0) {
- (void)fprintf(myout, "Tar: \'%s\' seek error\n", fname);
- done(ERREAD);
- }
- }
- }
- run : if (v_flag || j_flag) {
- (void)fprintf(myout, "a %s %ld blocks\n", p, blocks);
- }
- if (j_flag) {
- (void)fprintf(stderr, "> ");
- for (i=0; (c=getc(myinp))!='\n'; ) {
- if (i < sizeof(hblock->x.old.comment)-1) {
- hblock->x.old.comment[i++] = c;
- }
- }
- hblock->x.old.comment[i] = 0;
- } else {
- hblock->x.old.comment[0] = 0;
- }
- if (packok) {
- proctl(hblock->size, codesize);
- if (pktype == PKLZH) {
- proctl(hblock->x.old.srcsum, longcsum);
- proctl(hblock->x.old.srclen, st.st_size);
- } else /* if (z_bits) */ {
- (void)strcat(hblock->name, ".Z");
- }
- prcsum(hblock);
-
- if (rewroll(1) != 0) errproc(p);
- while (codesize-- > 0) {
- if ((c = rgetc()) == EOF) errproc(p);
- writebyte(c);
- }
- } else {/* common store file */
- prcsum(hblock);
-
- if ((blocks -= writearch(infile, st.st_size, fname)) != 0) {
- (void)fprintf(myout, "Tar: \'%s\' decreased size\n", fname);
- while (blocks-- > 0) nullblock(steptape());
- }
- }
- (void)close(infile);
-
- if (y_flag) {
- #ifdef MDSOS
- if (!(st.st_mode & S_IWRITE)) (void)chmod(fname, S_IWRITE);
- #endif
- if (unlink(fname)) {
- (void)fprintf(myout, "Tar: can\'t delete \'%s\'\n", fname);
- }
- }
- }